<?php

/*------------------------------------------------
*
*   Explay Engine Content Management System.
*   Copyright © 2008 Golovdinov Alexander.
*
*-------------------------------------------------
*
*   Official site: wwww.alex-home.spb.ru/explay.html
*   Contact e-mail: golovdinov@gmail.com
*
*   GNU General Public License original source:
*   http://www.gnu.org/licenses/gpl-3.0.html
*
------------------------------------------------*/

if (!defined ('EXPLAY')) exit;


class articlesController {
	
	private $data = ''; // Контент
	public $errors = array ();
	private $messages = array ();
	private $print_errors = false;
	private $print_messages = false;
	
	private $classes_methods = array ();
	
	/**************************************************/
	
	public $settings = array (); // настройки статей
	public $author_properties = false; // свойства автора статей
	public $bar = true; // бар XDDD
	
	/**
	 * Условия (фильтры)
	 */
	public $options_str = '';
	public $order = 'art_id';
	public $author = 0;
	public $blog = '';
	
	public $start = 0;
	public $number;
	/**
	 * Закончились условия
	 */
	
	public $top; // верхняя часть списка (форма для тегов или поиска)
	public static $main_url = '/articles/'; // основной УРЛ
	public $after_url = ''; // дополнительный УРЛ (параметр с поиском или тегом)
	
	private static $instance = false;
	public static function getInstance () {
		if (self::$instance === false) self::$instance = new articlesController;
			
		return self::$instance;
	}

	private function __construct () {}
	
	/**
	 * Загрузка класса (модуля)
	 *
	 * @param string $file полный адрес файла с классом
	 * @param string $classname название класса
	 */
	public function load_class ($file, $classname) {
		include $file;
		$methods = get_class_methods($classname);
		//print_r ($methods);
		//exit;
		foreach ($methods as $m) {
			$this->classes_methods[] = array ($classname, $m);
		}
	}
	
	
	/**
	 * Вызов несуществующего метода articlesController
	 *
	 * Необходимый метод ищется в подгруженных классах (модулях)
	 * Если метода нигде нет, то создается пользовательска ошибка
	 */
	public function __call ($method, $vars) {
		foreach ($this->classes_methods as $class) {
			if ($class[1] == $method) {
				eval ('$object = '.$class[0].'::getInstance(); $object->'.$method.'(); unset($object);'); // eval, конечно, плохо, но как еще?
				return;
			}
		}
		
		trigger_error("Called not exist class method: ".$method, E_USER_WARNING);
	}
	
	/**
	 * Вывод результата (ошибки, сообщений и контента)
	 */
	public function show_result () {
		if ($this->print_errors) {
			if (count ($this->errors) == 1) {
				site_error ($this->errors[0]);
			} else {
				$errstr = '';
				foreach ($this->errors as $err) {
					$errstr .= '<li>'.$err.'</li>';
				}
				$errstr = '<ul>'.$errstr.'</ul>';
				
				site_error ($errstr);
				unset ($errstr);
			}
		}
		
		if ($this->print_messages) {
			if (count ($this->messages) == 1) {
				site_message ($this->messages[0]);
			} else {
				$messstr = '';
				foreach ($this->messages as $mess) {
					$messstr .= '<li>'.$mess.'</li>';
				}
				$messstr = '<ul>'.$messstr.'</ul>';
				
				site_messgae ($messstr);
				unset ($messstr);
			}
		}
		
		if ($this->data) {
			print $this->data;
			unset ($this->data);
		}
		//trigger_error("Result empty", E_USER_WARNING);
	}
	
	/**
	 * Добаление ошибки
	 *
	 * @param string $message текст ошибки
	 */
	public function set_error ($message) {
		array_push ($this->errors, $message);
		$this->print_errors = true;
	}
	
	/**
	 * Добаление сообщения
	 *
	 * @param string $message текст сообщения
	 */
	public function set_message ($message) {
		array_push ($this->messages, $message);
		$this->print_messages = true;
	}
	
	/**
	 * Добавление контента
	 *
	 * @param string $data контент
	 */
	public function set_data ($data) {
		$this->data .= $data;
	}
	
	/**
	 * Загрузка настроек модуля статей
	 */
	public function load_settings () {
		
		$options = file ($_SERVER['DOCUMENT_ROOT'].'/modules/articles/admin/options.txt');
		
		foreach ($options as $opt) {
			$opt = explode ('=', $opt);	
			$this->settings[trim($opt[0])] = trim($opt[1]);
		}
		
		$this->number = $this->settings['onpage'];
		
	}
	
	/**
	 * Общий метод определения встроенных условий выборки статей
	 */
	public function load_default_filters () {
		
		if (!empty($_GET['page']))
			$this->start = (intval ($_GET['page']) - 1) * $this->number;
		
		// Если указан автор
		if ($this->author != 0)
			$this->add_filter ('art_author', $this->author);
		
		// Если автор передан в параметре	
		if (isset ($_GET['user'])) {
			
			$user = User::get_user ($_GET['user']);
			
			if ($user !== false) {
				
				CORE::set_page_title ('Блог '.$user['user_name'].' &mdash; '.CORE::$SITE['site_name']);
				
				$this->author_properties = $user;
				$this->set_author ($user['user_id']);
				
				$this->add_filter ('art_author', $this->author);
				self::$main_url = '/users/';
				$this->add_main_url ($user['user_login']);
				$this->add_main_url ('blog');
			}
		}
		
		// Если блог задан
		if ($this->blog != '')
			$this->add_filter ('art_category', $this->blog);
		
		// Если блог передан в параметре	
		if (isset ($_GET['cat']) && $_GET['cat'] != 'all' && $_GET['cat'] != 'articles' && $_GET['cat'] != 'comments') {
			
			$this->blog = addslashes (substr ($_GET['cat'], 0, 30));
			
			$this->add_filter ('art_category', $this->blog);
			
			if ($_GET['cat'] == 'all')
				$this->top .= Templater::display ('articles/bar_all.tpl');
		}
		
		if (isset ($_GET['cat'])) $this->add_main_url (addslashes (substr ($_GET['cat'], 0, 30)));
		
		// Если в параметре передан тег
		if (isset($_GET['tagname'])) {
	
			$tagname = addslashes (trim ($_GET['tagname']));
			$tagname = substr ($tagname, 0, 30);
		
			$view = new articlesView;
			$this->set_data ($view->tags_form ($tagname));
			unset ($view);
	
			
			if ($tagname != '') {
				
				$this->add_filter ('art_tags', "%{$tagname}%", 'LIKE');
				$this->add_after_url ('tagname', $tagname);
				$this->add_filter ('art_visible', 'on');
				
			}
			else site_error ('Какой тег искать? Может вам <a href="/articles/tags/">облаками</a> нравится?');
		}
		
		
		// Поиск
		if (isset ($_GET['searchfor'])) {
			
			$search = substr (addslashes ( strip_tags ($_GET['searchfor'])), 0, 31);
			
			if ($search != '') $this->prepare_search ($search);
			
			$view = new articlesView;
			$this->set_data ($view->search_form ($search));
			unset ($view);
		}
		
		// Если условия не заданы, то устанавливаем стандартные
		if ($this->options_str == '' && !isset($_GET['cat'])) {
			$this->add_filter ('art_rating', '-3', '>');
			$this->add_filter ('art_publik', 'yes');
		}		
		
		// Еслиэто модератор или пользователь просматривает свои статьи, то показываем звлоченные
		if ((!is_moderator() && $this->author != User::$properties['user_id']) || !is_registered())
			$this->add_filter ('art_visible', 'on');
		
		$this->add_filter ('art_like_page', 'no');		
		
	}
	
	/**
	 * Обработка поискового параметра
	 */
	private function prepare_search ($search_text) {
		// Фильтруем символы
		$bad = array("!","*","%","(",")","=","<",">","?","/","\\","|","&",":",";","'",'"',",","`","~");
		$bad_count = count($bad);
		for ($i=0; $i<$bad_count; ++$i) {
			$search_text = str_replace ($bad[$i], '', $search_text);
		}
	
		
		$words = explode (' ', $search_text);
		$count_words = 1;
		$search_options = '';
		
		foreach ($words as $word) {
			if ($count_words == 3) break;
			
			$word = trim($word);
			if (mb_strlen($word) >= 3) {
				$search_options .= ($search_options == '')
					? " (art_body LIKE '%{$word}%' OR art_header LIKE '%{$word}%') "
					: " OR (art_body LIKE '%{$word}%' OR art_header LIKE '%{$word}%') ";
				
				array_push (articlesModel::$search_words, $word);
			}
			
			++$count_words;
		}
		
		if ($search_options != '') {
			$this->add_filter ('('.$search_options.')');
			$this->add_filter ('art_visible', 'on');
		}
				
		$this->add_after_url ('searchfor', urlencode($search_text));
		
	}
	
	/**
	 * Добаление условия выборки списка статей
	 *
	 * @param string $field имя поля
	 * @param string $value значение поля (необязательный параметр)
	 * @param string $operator оператор между названием поля и значением (необязательный параметр, по-умолчанию "=")
	 * @param string $logic_operator оператор между текущем условием и предыдущим (необязательный параметр, по-умолчанию "AND")
	 */
	public function add_filter ($field, $value = '', $operator = '=', $logic_operator = 'AND') {
		if ($value == '')
			$this->options_str .= ($this->options_str == '')
				? " $field "
				: " $logic_operator $field ";
		else
			$this->options_str .= ($this->options_str == '')
				? " $field $operator '$value' "
				: " $logic_operator $field $operator '$value' ";
	}
	
	/**
	 * Сбрасывает все установленные фильтры
	 */
	public function clear_filters () {
		$this->options_str = '';
	}
	
	/**
	 * Определяет текущюю страницу
	 */
	public function init_page () {
		if (!empty ($_GET['page'])) $this->start = (int) (intval ($_GET['page']) - 1) * $this->settings['onpage'];	
	}
	
	/**
	 * Добавляет параметр к главному УРЛу в заголовке
	 *
	 * @param string $var параметр
	 */
	public function add_main_url ($var) {
		self::$main_url .= $var.'/';
	}
	
	/**
	 * Добавляет параметр к дополнительному УРЛу в заголовке
	 *
	 * @param string $var название параметра
	 * @param string $value значение параметра
	 */
	public function add_after_url ($var, $value) {
		$this->after_url .= ($this->after_url == '')
			? '?'.$var.'='.$value
			: '&'.$var.'='.$value;
	}
	
	/**
	 * Указывает какого юзера выводисть сатьи
	 *
	 * @param integer $id id пользователя
	 */
	public function set_author ($id) {
		$this->author = $id;
	}
	
	/**
	 * Указывает поле по которому производится сортировка
	 *
	 * @param string $order название поля
	 */
	public function set_order ($order) {
		$this->order = $order;
	}
	
	/**
	 * Отключение "бара"
	 */
	public function set_bar_off () {
		$this->bar = false;
	}
	

}